 /*
* This serves as a base class that extends the Statemachine+ Event Engine and MovieClip
* and adds common functionality to most components
* like  access to preloading, eventDispatcher
*
* In addition it also operates in a late binding
* separation of script and ui, similar to how linkage works
* with components and clips in the library. The difference is that
* this binding happens later,  courtesy of David Yangs prototype
* chain hacking.
*
* This allows complete separation of code from
* ui, and simpler than in using composition (passing in a reference)
*
* @author Troy Gardner
* @version
*/
import com.troyworks.framework.IApplication;
import com.troyworks.framework.ui.IHaveChildrenComponents;
import com.troyworks.framework.ui.MCBackground;
import com.troyworks.framework.ui.MCButton;
import com.troyworks.hsmf.AEvent;
import com.troyworks.hsmf.Signal;

//parent chain: HsmfE (statemachine + events)->MovieClip->Object
class com.troyworks.framework.ui.BaseComponent2 extends com.troyworks.hsmf.Hsmf  {
	//public var app : IApplication;
	// the base component supports
	// preloading, transition in, active, transition out to inactive,
	// those that have status provide it
	public static var EVT_LOADED : String = "EVT_LOADED";
	public static var EVT_READY : String = "EVT_READY";
	public static var EVT_TRANSIN : String = "EVT_";


	public static var ASSETS_LOADED_SIG : Signal = Signal.getNext("ASSETS_LOADED");
	public static var STAGE_RESIZE_SIG : Signal = Signal.getNext("STAGE_RESIZE_EVT");

	public static var ASSETS_LOADED_EVT : AEvent = new AEvent(ASSETS_LOADED_SIG);
	public static var STAGE_RESIZE_EVT : AEvent = new AEvent(STAGE_RESIZE_SIG);
// capture positions
	public var _ox : Number = null;
	public var _oy : Number = null;
	public var _owidth : Number = null;
	public var _oheight : Number = null;
	public var _oxscale : Number = null;
	public var _oyscale : Number = null; 
	//actual height
	public var _oawidth : Number = null;
	public var _oaheight : Number = null;

	public var _o_wh_asp : Number = null;
	public var _o_hw_asp : Number = null;

	public var isFullScreenMode : Boolean = false;
	public var followStage : Boolean = true;
	public var hAlign : Boolean = null;
	public var vAlign : Boolean = null;
	public var centerMe : Boolean = false;
	public var mcbuttons : Array = new Array();

	public var codeGen : Number = -1;
	public var owner : IHaveChildrenComponents;
	public var isLoaded : Boolean;
	public var isReady : Boolean;

	function BaseComponent2(initialState : Function, hsmfName : String, aInit : Boolean)
	{
		super ((initialState != null)?initialState: s_initial, (hsmfName != null)?hsmfName:_name+":BaseComponent2");
		if(aInit == null || aInit == true){
			init();
		}
	}

		public function onChildClipLoad(_mc : MovieClip) : Void{
			var btn :MCButton = null;// _mc;//MCButton(_mc);
			if(btn != null){
			//	 trace("HIGHLIGHTG BaseComponent onChildClipLoad addingListenerFor " +btn.click_evt);
			btn.addEventListener(btn.click_evt, this, this.onChildClipEvent);
			mcbuttons.push(btn);
			}
	}
	//public function onChildClipReady(_mc : MovieClip) : Void {
	//}
	public function onChildClipEvent(e : Object) : Void{
		trace("000000000000000000000000000000000000000000000000000000");
		trace("0000000000000000000000000BaseComponent.onChildClipEvent00000000000000000000000000000");
		trace(util.Trace.me(e, "evt ", false));
		trace("000000000000000000000000000000000000000000000000000000");
		trace("000000000000000000000000000000000000000000000000000000");
		trace("000000000000000000000000000000000000000000000000000000");
	}
	/*******************************************************
	 * for a given movie passed in capture it's x, y, width height, into 
	 * another object (defaults to the same)
	 * 
	 * Note this can get tricky.
	 * 
	 * There is the library representation of the item (_xscale = 100, _yscale = 100)
	 * There is the onscreen representation as when the item loads
	 * There is the scaled version of it
	 * The version of it with content inside of it (which distorts the width, height properties)
	 * When being used with a viewport.
	 */
	public static function snapshotDimensions(a_mc : MovieClip, to_mc : Object, override_width : Number, override_height : Number) : Void {
		var s_mc : MovieClip = a_mc;
		to_mc = (to_mc == null)?a_mc:to_mc;
		//////Find the viewport on the content/////////////////////////
		// note that when a movie clip is exported from the library, a wrapper swf is created
		//
		var viewport : MovieClip = null;
		if (a_mc.viewport_mc == null) {
			for (var i in a_mc) {
				var b = a_mc[i];
			//	trace(i+" = "+b);
				if (b.viewport_mc != null) {
				//	trace("found viewport l1");
					viewport = b.viewport_mc;
					break;
				}
			}
		} else {
			viewport = a_mc.viewport_mc;
		}
		/////Get the original dimension pre scaling and positioning ////////////
		if (viewport != null) {
			trace("has a clipping region!!!!!!!!!!!!!!");
			s_mc = viewport;
			//offset between viewport and published content.
			to_mc.vp_ox_offset = viewport._x;
			to_mc.vp_oy_offset = viewport._y;
			to_mc.vp_owidth = viewport._width;
			to_mc.vp_oheight = viewport._height;
			trace(" offset x "+viewport._x+" y "+viewport._y);
			//scale factor between viewport and actual (masked) movie dimensions (as mask shows all stuff on stage)
			
			to_mc.vp_owscale = viewport._width/a_mc._width;
			to_mc.vp_ohscale = viewport._height/a_mc._height;
			trace("vp_owscale " + to_mc.vp_owscale + "  " +viewport._width + "/" +a_mc._width ); 
			//
			to_mc._owidth = s_mc._width;
			to_mc._oheight = s_mc._height;
			to_mc._o_wh_asp = s_mc._width/s_mc._height;
			to_mc._o_hw_asp = s_mc._height/s_mc._width;
		} else {
			// NO viewport
			to_mc.vp_ox_offset = 0;
			to_mc.vp_oy_offset = 0;
			to_mc.vp_owscale = 1;
			to_mc.vp_ohscale = 1;
			to_mc.vp_owidth = s_mc._width;
			to_mc.vp_oheight = s_mc._height;

		}
		to_mc._ox = s_mc._x;
		to_mc._oy = s_mc._y;
		to_mc._owidth = s_mc._width;
		to_mc._oheight = s_mc._height;
		to_mc._oxscale = s_mc._xscale;
		to_mc._oyscale = s_mc._yscale;
		//actual height
		to_mc._oawidth = Math.round(to_mc._width / to_mc._xscale*100);
		to_mc._oaheight = Math.round(to_mc._height / to_mc._yscale*100);

		to_mc._o_wh_asp = s_mc._width/s_mc._height;
		to_mc._o_hw_asp = s_mc._height/s_mc._width;
		trace( util.Trace.me(to_mc, "ERROR SNAPSHOT DIMENSIONS ", true));
		trace(" captureOriginalAspect "+to_mc._url+" "+to_mc._width);
	}
	public function center() : Void {
		//Center
		//	trace(this._name + "BaseComponent.center()" + Stage.width + " " + Stage.height  + " " + this._width + " " + this._height);
		this._x = (Stage.width - this._width) / 2;
		this._y = (Stage.height - this._height) / 2;
		//	trace("setting to x " + this._x + " y " + this._y);
		
	}
	public static function centerClipTo(still_mc : MovieClip, moving_mc : MovieClip, override_width : Number, override_height : Number, scaleW : Number, scaleH : Number) : Void
	{
		//Center
		//	trace(this._name + "BaseComponent.center()" + Stage.width + " " + Stage.height  + " " + this._width + " " + this._height);
		var dw : Number = (override_width == null)? still_mc._width:override_width;
		var dh : Number = (override_height == null)? still_mc._height:override_height;
		var iw : Number = moving_mc._width /scaleW;
		var ih : Number = moving_mc._height/scaleH;
		
//		trace("CENTERING  Moving: " + w + ", " + h +" "
		var resX : Number = 0;
		if(dw > iw){
			resX = (dw - iw) / 2;
		}else{
			resX = (iw - dw) / 2;
		}
		var resY : Number = 0;
		if(dh > ih){
			resY = (dh - ih) / 2;
		}else{
			resY = (ih - dh) / 2;
		}
		trace("CENTERING dw " + dw + " dh " + dh + " iw " + iw + " ih " + ih + "== resX " + resX + " resY " + resY);
		moving_mc._x = resX;
		moving_mc._y = resY;
		//	trace("setting to x " + this._x + " y " + this._y);
		
	}
	function alignH(x : String, still_mc : MovieClip, moving_mc : MovieClip, snapToWholePixel : Boolean) : Number
	{
		trace ("alignH " + x + " " + still_mc + " " + moving_mc + " snap " + snapToWholePixel);
		var r : Number = 0;
		switch (x.toUpperCase ())
		{
			//assume that mask is at 0,0 so no xpos is needed
			case "CENTER" :
				r = (still_mc._width - moving_mc._width) / 2;
				break;
			case "RIGHT" :
				r = (still_mc._width - moving_mc._width);
				break;
			case "LEFT" :
			default :
				return 0;
		}
		if (snapToWholePixel)
		{
			return Math.round (r);
		}else
		{
			return r;
		}
	}
	function alignV(y : String, still_mc : MovieClip, moving_mc : MovieClip, snapToWholePixel : Boolean) : Number
	{
	//	trace ("alignV " + y+ " " + still_mc + " " + moving_mc + " snap " + snapToWholePixel);
		var r : Number = 0;
		switch (y.toUpperCase ())
		{
			//assume that mask is at 0,0 so no ypos is needed
			case "MIDDLE" :
				r = (still_mc._height - moving_mc._height) / 2;
				break;
			case "BOTTOM" :
				r = (still_mc._height - moving_mc._height);
				break;
			case "TOP" :
			default :
				return 0;
		}
		if (snapToWholePixel)
		{
			return Math.round (r);
		}else
		{
			return r;
		}
	}
	public static function scaleTo(still_mc : MovieClip, moving_mc : MovieClip , override_width : Number, override_height : Number, viewport_width : Number, viewport_height : Number) : Void {
		trace("HIGHLIGHT scaleTo");
		trace ("Stage.width " + Stage.width + " still  mc " + still_mc._width + " moving  mc " + moving_mc._width + " override " + override_width);
		trace ("Stage.height " + Stage.height + " still  mc " + still_mc._height+ " moving  mc " + moving_mc._height+ " override " + override_height);
		////////////////////////////////////
		//  target to scalee's actual height 
		////////////////////////////////////
		var	t_w : Number = null;
		if(viewport_width == null){
			trace(" not using viewport");
			if(moving_mc._oawidth ==null){
				trace("using current actual _width");
				t_w = moving_mc._width;
			}else{
				trace("using original actual _width");

				t_w = moving_mc._oawidth;
			}
		}else{
			trace(" using viewport dimensions");
			t_w = viewport_width;
		};
		var t_h : Number = null;
		if(viewport_height == null){
			t_h = (moving_mc._oaheight ==null)?moving_mc._height:moving_mc._oaheight;
		}else{
			t_h =viewport_height;
		} 
		////////////////////////////////////
		//   desired height 
		////////////////////////////////////
		var dw : Number = override_width ;
		var dh : Number = override_height;
		var scaleW : Number = (viewport_width == null)?1: moving_mc.vp_owscale;
		var scaleH : Number = (viewport_height == null)?1: moving_mc.vp_ohscale;

	//	trace("  scaling W " + scaleW + "  H " + scaleH);
		var p_asp : Number = t_w/t_h;
		var p2_asp : Number = t_h/t_w;
		var still_asp : Number = override_width/override_height;
	//	if (this.isFullScreenMode)
		{
			//o_wh_asp and o_hw_asp are the original captured aspect ratio,
			//this is as captured from the IDE, and NOT the actionscript,
			//in order to get accurate onscreen representation.
			//scale to smallest dimension based on the relative aspect ratio
	//		trace("PHOTO DIMENSIONS w:" + t_w + " h:" + t_h + " asp " + p_asp);
	//		trace("DESIRED DIMENTSION w:" + dw + " h: " + dh + " asp "   + still_asp);
			var asRatios : Number = (p_asp /still_asp);
			trace ("aspect ratio " + asRatios + "  " + still_asp);
			var resizeAnyWay : Boolean = (asRatios==1) && t_w != dw; 
			if (asRatios>1 || resizeAnyWay )
			{
				trace ("resizing width first to:" + dw);
				moving_mc._width = dw/  scaleW;
				moving_mc._height = dw / p_asp / scaleH;
				moving_mc._x = 0;
				//centerClipTo (still_mc , moving_mc, dw, dh, scaleW, scaleH);
				center2(moving_mc, {_width:dw, _height:dh, _x:0, _y:0});
			} else if (asRatios<1)
			{
				trace ("resizing height first to:" + dh );
				moving_mc._width = dh / p2_asp / scaleW;
				moving_mc._height = dh / scaleH;
				moving_mc._x = 0;
				center2(moving_mc, {_width:dw, _height:dh, _x:0, _y:0});
			//centerClipTo (still_mc , moving_mc , dw, dh, scaleW, scaleH);
			} else
			{
				trace ("NOT resizing");
			}
			trace("HIGHLIGHTO scaleTo res:  " + moving_mc._width + "  " + moving_mc._height);
			//this.playerNav_mc._x = ((t_w - (this.playerNav_mc._width + this.playerNav_mc.logo_mc._width )) / 2) + this.playerNav_mc.logo_mc._width + 30 ;
			//			this.playerNav_mc._y = (t_h - this.playerNav_mc._height) / 2;
			
	//	} else
	//	{
	//		this.resetSizeAndPosition ();
		}
	}
public static function center2(_mc:MovieClip, back_mc:Object):Void {
	//Center
	trace("HIGHLIGHT center2");
	// See if they are referrign to Stage or a component or not.
	var w :Number= (back_mc._width != null) ? back_mc._width : back_mc.width;
	var h :Number= (back_mc._height != null) ? back_mc._height : back_mc.height;
	trace("w " + w + " h " + h);
	if (false) {
		//works with non scaled clips
		_mc._x = back_mc._x+((w-_mc._width)/2);
		_mc._y = back_mc._y+((h-_mc._height)/2);
	} else {
		//TODO: tring to figure out scaled clip center.
		// the scale factor between whe content (not the viewport)
		// was first loaded and where it is now.
		// want >1 if it's been scaled up.
		trace("mc._width " + _mc._width + " ow " + _mc._oawidth);
		var sxf:Number = _mc._width/_mc._oawidth;
		var syf:Number = _mc._height/_mc._oaheight;
		trace("sxf " + sxf + " syf " + syf);
		var x_offset:Number = (sxf*_mc.vp_ox_offset);
		var y_offset :Number= (syf*_mc.vp_oy_offset);
		trace("xoffset "+x_offset+" y offset "+y_offset);
		trace("_mc.vp_owidth " + _mc.vp_owidth + " " +  _mc.vp_oheight);
		var ww:Number = _mc.vp_owidth*sxf;
		var yy:Number = _mc.vp_oheight*syf;
		trace("ww " + ww + " yy " + yy);
		_mc._x = back_mc._x+((w-ww)/2)-x_offset;
		_mc._y = back_mc._y+((h-yy)/2)-y_offset;
			trace("resX " + _mc._x + " resY " + _mc._y);
		
	}
	//}
}
	/*function scaleTo2(_mc : MovieClip, back_mc : MovieClip) : Void {
		trace(_mc+" ScaleTo -> "+back_mc);
		//Scale
		var sw : Number = (back_mc._width != null) ? back_mc._width : back_mc.width;
		var sh : Number = (back_mc._height != null) ? back_mc._height : back_mc.height;
			if(_mc._o_wh_asp == null){
				
			}
		var asRatios = (sw/sh)/_mc._o_wh_asp;
		trace("aspect ratio "+asRatios+"  "+_mc._o_wh_asp);
		var resizeAnyWay = (asRatios==1) && sw != _mc._width; 
				if (asRatios>1 || resizeAnyWay ){
			trace("resizing by width first");
			_mc._width = sw/_mc.vp_owscale;
			_mc._height = sw/_mc._o_wh_asp/_mc.vp_ohscale;
			this.center(_mc, back_mc);
		} else if (asRatios>1) {
			trace("resizing by height ");
			_mc._width = sh/_mc._o_hw_asp/_mc.vp_owscale;
			_mc._height = (sh/_mc.vp_ohscale);
			this.center(_mc, back_mc);
		} else {
			trace("NOT resizing");
		}
	}*/
	public function scaleToStage(override_width : Number, override_height : Number) : Void {
		trace ("Stage.width " + Stage.width + " mc " + this._width);
		trace ("Stage.height " + Stage.height + " mc " + this._height);
		//Scale
		var	sw : Number = (override_width == null)? Stage.width: override_width;
		var sh : Number = (override_height == null)?Stage.height: override_height;
	
	//	if (this.isFullScreenMode)
		{
			//o_wh_asp and o_hw_asp are the original captured aspect ratio,
			//this is as captured from the IDE, and NOT the actionscript,
			//in order to get accurate onscreen representation.
			//scale to smallest dimension based on the relative aspect ratio
			var asRatios : Number = (sw / sh) / this._o_wh_asp;
			trace ("aspect ratio " + asRatios + "  " + this._o_wh_asp);
			if (asRatios < 1 )
			{
				trace ("resizing width first");
				this._width = sw;
				this._height = sw / this._o_wh_asp;
				this.center ();
			} else if (asRatios > 1)
			{
				trace ("resizing height first" );
				this._width = sh / this._o_hw_asp;
				this._height = sh;
				this.center ();
			} else
			{
				trace ("NOT resizing");
			}
			//this.playerNav_mc._x = ((sw - (this.playerNav_mc._width + this.playerNav_mc.logo_mc._width )) / 2) + this.playerNav_mc.logo_mc._width + 30 ;
			//			this.playerNav_mc._y = (sh - this.playerNav_mc._height) / 2;
			
	//	} else
	//	{
	//		this.resetSizeAndPosition ();
		}
	}
		public function resetSizeAndPosition() : Void
	{
		this._x = this._ox;
		this._y = this._oy;
		this._width = this._owidth;
		this._height = this._oheight;
	}
	//Stage Resize
	public function onResize() : Void {
		trace("*********** STAGE_RESIZE A ***********");
		Q_dispatch(STAGE_RESIZE_EVT);
		trace("*********** STAGE_RESIZE B ***********");
		if(centerMe){
			trace("________CENTERING?++++++++");
		//	this.center ();
		}
	}
	//similar to a hittest but doesn't consider clips blocking the view of the mouse
	// and allows for padding (both positive and negative)d, for proximity purposes.
	public function mouseIsOverMe(padding : Number) : Boolean
	{
		padding = (padding == null) ?0 : padding;
		return ((0 - padding) < this._xmouse && this._xmouse < (this._width + padding)) && ((0 - padding) < this._ymouse &&this._ymouse < (this._height + padding));
	}
	/*..PSEUDOSTATE...............................................................*/
	function s_initial(e : AEvent) : Void
	{
		//trace("************************* s_initial " + util.Trace.me(e)+" ******************");
		onFunctionEnter ("s_initial-", e, []);
		if(e.sig != Q_TRACE_SIG){
			//Q_INIT(s0_viewAssetsUnLoaded);
		}
	}
	/*.................................................................*/
	function s0_viewAssetsUnLoaded(e : AEvent) : Function
	{
		this.onFunctionEnter ("s0_viewAssetsUnLoaded-", e, []);
		switch(e.sig)
		{
			case ASSETS_LOADED_SIG:{
				Q_TRAN(s0_viewAssetsLoaded);
				return null;
			}
		}
		return s_top;
	}
	/*.................................................................*/
	function s0_viewAssetsLoaded(e : AEvent) : Function
	{
		this.onFunctionEnter ("s0_viewAssetsLoaded-", e, []);
		switch(e.sig)
		{
			case Q_EXIT_SIG :
			{
				Q_TRAN(s0_viewAssetsUnLoaded);
				return null;
			}
			case Q_INIT_SIG :
			{
				Q_TRAN(s1_creatingView);
				return null;
			}
		}
		return s_top;
	}
	//////////////////////// LEVEL 1 STATES////////////////////////////
	/*.................................................................*/
	function s1_viewNotCreated(e : AEvent) : Function
	{
		this.onFunctionEnter ("s1_viewNotCreated-", e, []);
	/*	switch(e.sig)
		{

		}*/
		return s0_viewAssetsLoaded;
	}	/*.................................................................*/
	function s1_creatingView(e : AEvent) : Function
	{
		this.onFunctionEnter ("s1_creatingView-", e, []);
		switch(e.sig)
		{
			case Q_INIT_SIG :
			{
				Q_INIT(s1_viewCreated);
				return null;
			}
		}
		return s0_viewAssetsLoaded;
	}
	/*.................................................................*/
	function s1_viewCreated(e : AEvent) : Function
	{
		this.onFunctionEnter ("s1_creatingView-", e, []);
		switch(e.sig)
		{
			case Q_ENTRY_SIG :
			{
				isReady = true;
				return null;
			}
		}
		return s0_viewAssetsLoaded;
	}
	/*.................................................................*/
	function s1_destroyingView(e : AEvent) : Function
	{
		this.onFunctionEnter ("s1_destroyingView-", e, []);
	/*	switch(e.sig)
		{
		}*/ 
		return s0_viewAssetsLoaded;
	}
}
